/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package logging

import (
	"sync"

	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/core/logging/api"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/core/logging/metadata"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/core/logging/modlog"
)

type Logger struct {
	instance api.Logger // access only via Logger.logger()
	module   string
	once     sync.Once
}

var loggerProviderInstance api.LoggerProvider
var loggerProviderOnce sync.Once

type Level int

const (
	CRITICAL Level = iota
	ERROR
	WARNING
	INFO
	DEBUG
)

const (
	loggerNotInitializedMsg = "Default logger initialized (please call logging.InitLogger if you wish to use a custom logger)"
	loggerModule            = "ichainsdk/common"
)

func NewLogger(module string) *Logger {
	return &Logger{module: module}
}

func loggerProvider() api.LoggerProvider {
	loggerProviderOnce.Do(func() {
		loggerProviderInstance = modlog.LoggerProvider()
		logger := loggerProviderInstance.GetLogger(loggerModule)
		logger.Debug(loggerNotInitializedMsg)
	})
	return loggerProviderInstance
}

func Initialize(l api.LoggerProvider) {
	loggerProviderOnce.Do(func() {
		loggerProviderInstance = l
		logger := loggerProviderInstance.GetLogger(loggerModule)
		logger.Debug("Logger provider initialized")
	})
}

func SetLevel(module string, level Level) {
	modlog.SetLevel(module, api.Level(level))
}

func GetLevel(module string) Level {
	return Level(modlog.GetLevel(module))
}

func IsEnabledFor(module string, level Level) bool {
	return modlog.IsEnabledFor(module, api.Level(level))
}

func LogLevel(level string) (Level, error) {
	l, err := metadata.ParseLevel(level)
	return Level(l), err
}

func (l *Logger) Fatal(args ...interface{}) {
	l.logger().Fatal(args...)
}

func (l *Logger) Fatalf(format string, args ...interface{}) {
	l.logger().Fatalf(format, args...)
}

func (l *Logger) Fatalln(args ...interface{}) {
	l.logger().Fatalln(args...)
}

func (l *Logger) Panic(args ...interface{}) {
	l.logger().Panic(args...)
}

func (l *Logger) Panicf(format string, args ...interface{}) {
	l.logger().Panicf(format, args...)
}

func (l *Logger) Panicln(args ...interface{}) {
	l.logger().Panicln(args...)
}

func (l *Logger) Print(args ...interface{}) {
	l.logger().Print(args...)
}

func (l *Logger) Printf(format string, args ...interface{}) {
	l.logger().Printf(format, args...)
}

func (l *Logger) Println(args ...interface{}) {
	l.logger().Println(args...)
}

func (l *Logger) Debug(args ...interface{}) {
	l.logger().Debug(args...)
}

func (l *Logger) Debugf(format string, args ...interface{}) {
	l.logger().Debugf(format, args...)
}

func (l *Logger) Debugln(args ...interface{}) {
	l.logger().Debugln(args...)
}

func (l *Logger) Info(args ...interface{}) {
	l.logger().Info(args...)
}

func (l *Logger) Infof(format string, args ...interface{}) {
	l.logger().Infof(format, args...)
}

func (l *Logger) Infoln(args ...interface{}) {
	l.logger().Infoln(args...)
}

func (l *Logger) Warn(args ...interface{}) {
	l.logger().Warn(args...)
}

func (l *Logger) Warnf(format string, args ...interface{}) {
	l.logger().Warnf(format, args...)
}

func (l *Logger) Warnln(args ...interface{}) {
	l.logger().Warnln(args...)
}

func (l *Logger) Error(args ...interface{}) {
	l.logger().Error(args...)
}

func (l *Logger) Errorf(format string, args ...interface{}) {
	l.logger().Errorf(format, args...)
}

func (l *Logger) Errorln(args ...interface{}) {
	l.logger().Errorln(args...)
}

func (l *Logger) logger() api.Logger {
	l.once.Do(func() {
		l.instance = loggerProvider().GetLogger(l.module)
	})
	return l.instance
}
